home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / ada / gwuada_6.zip / PARSER.C < prev    next >
C/C++ Source or Header  |  1993-10-24  |  24KB  |  927 lines

  1. /*
  2.     GWAda Development Environment for 386/486 PCs   
  3.     Copyright (C) 1993, Arthur Vargas Lopes  & Michael Bliss Feldman
  4.                         vlopes@vortex.ufrgs.br mfeldman@seas.gwu.edu
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; version 2 of the License.    
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. /* Parser.c */
  21.  
  22. #include "externs.h"
  23. #include "defines.h"
  24.  
  25. char *strupr(char *string);
  26. char *strcat(char *string1, const char *string2);
  27.  
  28.  
  29. typedef struct {
  30.     char yytext[AVL_MAX_LINEL + 1];
  31.     AVL_LINE_PTR temp;  /* Full source line */
  32.     int    yyleng;
  33.     int    code;
  34.     int    line_no;
  35.     int    line_col;
  36.     } TOKEN_TYPE;
  37.  
  38.  
  39. typedef struct {  /*  I/O structure  */
  40.     char        buffer[AVL_MAX_LINEL + 40];
  41.     char        last_token[AVL_MAX_LINEL + 1];
  42.     char        decimal_point;
  43.     int         size;
  44.     int         ibuf;
  45.     int         line_no;
  46.     int         look_ahead;
  47.     int         look_ahead_c[5];
  48.     int         look_ahead_t;
  49.     TOKEN_TYPE look_ahead_tcode[3];
  50.     } IO_TYPE;
  51.  
  52.  
  53.  
  54. IO_TYPE io_size;
  55.  
  56. #include "bsearch.c"
  57.  
  58.  
  59. void AVL_START_UP()
  60. {
  61.     int     ch;
  62.     char msg[100];
  63.     AVL_EDIT_WINDOW_PTR w;
  64.     w = &avl_windows[avl_window];
  65.     io_size.decimal_point     = '.';
  66.     io_size.look_ahead = 0;
  67.     io_size.line_no = w -> current_line -> line_no;
  68.     io_size.ibuf = w -> txt_col;
  69.     io_size.look_ahead_t = 0;
  70.     sprintf(io_size.buffer, w -> current_line -> line);
  71.     io_size.size = strlen(io_size.buffer);
  72.     sprintf(io_size.last_token,"THIS_IS_THE_END_OF_THE_FILE");
  73. }
  74.     
  75.  
  76. int AVL_NEXT()
  77. {
  78.     AVL_EDIT_WINDOW_PTR w;
  79.     AVL_LINE_PTR temp, temp2;
  80.     int     ch;
  81.     w = &avl_windows[avl_window];
  82.     if (io_size.look_ahead) { /* There is a look ahead char in the queue */
  83.         ch = io_size.look_ahead_c[0];
  84.         io_size.look_ahead_c[0] = io_size.look_ahead_c[1];
  85.         io_size.look_ahead_c[1] = io_size.look_ahead_c[2];
  86.         io_size.look_ahead_c[2] = io_size.look_ahead_c[3];
  87.         io_size.look_ahead_c[3] = io_size.look_ahead_c[4];
  88.         io_size.look_ahead -= 1;
  89.         return ch;
  90.         }
  91.     if (io_size.ibuf >= io_size.size)  {
  92.         if (w -> current_line -> next == w -> head)  
  93.             sprintf(io_size.buffer," \n THIS_IS_THE_END_OF_THE_FILE \" \n THIS_IS_THE_END_OF_THE_FILE  ");
  94.         else {
  95.             w -> current_line = w -> current_line -> next;
  96.             sprintf(io_size.buffer,"%s\n", w -> current_line -> line);
  97.             io_size.line_no = w -> current_line -> line_no;
  98.             }
  99.         io_size.size = strlen(io_size.buffer);
  100.         io_size.ibuf = 0;
  101.         }
  102.     ch = io_size.buffer[io_size.ibuf++];
  103.     if (ch == 26) ch = ' ';
  104.     if (ch == 0) return ' ';
  105.     return ch;
  106. }
  107.  
  108. void BACK(int     ch)
  109. {
  110.     if (io_size.look_ahead > 4)  {
  111.         AVL_ERROR("Too many look ahead bytes. SYSTEM ERROR...");
  112.         exit(1);
  113.         }
  114.     io_size.look_ahead_c[io_size.look_ahead++] = ch;
  115. }
  116.  
  117.  
  118. int IS_DIGIT(int ch, int base, int *n)  
  119. {
  120.     int     num;
  121.     char msg[40];
  122.     *n = 0;
  123.     if (ch >= 'A' && ch <= 'F')
  124.         num = ch - 'A' + 11;
  125.     else if (ch >= '0' && ch <= '9') 
  126.         num = ch - '0';
  127.     else 
  128.         return 0;
  129.     sprintf(msg,"%c in %d base ", ch, base);
  130.     if (num < 0 || num >= base)
  131.         AVL_ERROR(strcat("Based number with invalid digit ==> ",msg));
  132.     *n = num;
  133.     return 1;
  134. }
  135.  
  136. void BACK_T(TOKEN_TYPE tk)
  137. {
  138.     if (io_size.look_ahead_t > 2) {
  139.         AVL_ERROR("Too many look ahead tokens. SYSTEM ERROR...");
  140.         exit(1);
  141.         }
  142.     io_size.look_ahead_tcode[io_size.look_ahead_t++] = tk;
  143. }
  144.     
  145.  
  146. TOKEN_TYPE AVL_SCAN()
  147. {
  148.     int     ch, lch;
  149.     int     is_real = 0;
  150.     int     is_based = 0;
  151.     int     base = 10;
  152.     int     is_expo = 0;
  153.     int     string_mark;
  154.     int     temp;
  155.     static TOKEN_TYPE tk;
  156.     AVL_EDIT_WINDOW_PTR w;
  157.     char yytext[AVL_MAX_LINEL + 1];
  158.     w = &avl_windows[avl_window];
  159.  
  160.     if (io_size.look_ahead_t) {
  161.         tk = io_size.look_ahead_tcode[0];
  162.         io_size.look_ahead_tcode[0] = io_size.look_ahead_tcode[1];
  163.         io_size.look_ahead_tcode[1] = io_size.look_ahead_tcode[2];
  164.         io_size.look_ahead_t -= 1;
  165.         return tk;
  166.         }
  167.  
  168.     tk.yyleng = 0;
  169.     tk.yytext[0] = '\0';
  170. again:
  171.     /* First skip blanks */
  172.     while (isspace(ch = AVL_NEXT()));
  173.     /* Test comment */
  174.     if (ch == '-') {
  175.         ch = AVL_NEXT();
  176.         if (ch == '-') { /* Now reject til end of line */
  177.             while ((ch = AVL_NEXT()) != '\n');
  178.             goto again;
  179.             }
  180.         BACK('-');
  181.         BACK(ch);
  182.         }
  183.     else BACK(ch);
  184.     ch = AVL_NEXT();
  185.  
  186.     /* Now let's see what we got */
  187.  
  188.     tk.line_no  = io_size.line_no;
  189.     tk.line_col = io_size.ibuf;
  190.     tk.temp = w -> current_line;
  191.     if (isalpha(ch)) {  /* Got an object's name */ 
  192.         lch = ' ';
  193.         do {
  194.             if (tk.yyleng >= AVL_MAX_LINEL)  {
  195.                 tk.yytext[tk.yyleng] = '\0';
  196.                 AVL_ERROR(strcat("Symbol too long => ", tk.yytext));
  197.                 }
  198.             if (ch == '-' && lch == '-') {
  199.                 tk.yytext[tk.yyleng] = '\0';
  200.                 AVL_ERROR(strcat("Do not repeat _ ==> ", tk.yytext));
  201.                 }
  202.             tk.yytext[tk.yyleng++] = ch;
  203.             lch = ch;
  204.             ch = AVL_NEXT();
  205.             } while (isalpha(ch) || isdigit(ch) || ch == '_');
  206.         tk.yytext[tk.yyleng] = '\0';
  207.         strcpy(yytext,tk.yytext);
  208.         strupr(yytext);
  209.         if (lch == '_') 
  210.             AVL_ERROR(strcat("_ can't terminate an object's name ==> ", tk.yytext));
  211.         BACK(ch);
  212.         if (tk.code == XATTMARK) {  /* See if previous token was an ' */
  213.             lch = IS_ATT(yytext);
  214.             if (lch == 0)
  215.                 AVL_ERROR(strcat("Invalid attribute ==> ", tk.yytext));
  216.             tk.code = lch;
  217.             }
  218.         else {
  219.             if (!strcmp(yytext,"REM"))
  220.                 tk.code = XMULT;
  221.             else if (!strcmp(yytext,"MOD"))
  222.                 tk.code = XMULT;
  223.             else if (!strcmp(yytext,"AND"))
  224.                 tk.code = XLOG;
  225.             else if (!strcmp(yytext,"OR"))
  226.                 tk.code = XLOG;
  227.             else
  228.                 tk.code = IS_KEYWORD(yytext);
  229.             if (tk.code == 0)
  230.                 if (strcmp(io_size.last_token,yytext))
  231.                     tk.code = XID;
  232.             }
  233.         return tk;
  234.         }
  235.  
  236.                         
  237.     if (isdigit(ch))  {  /* Got a numeric literal */
  238.         lch = ' ';
  239.         do {
  240.             if (tk.yyleng >= AVL_MAX_LINEL)  {
  241.                 tk.yytext[tk.yyleng] = '\0';
  242.                 AVL_ERROR(strcat("Numeric literal too long ==> ", tk.yytext));
  243.                 }
  244.             if (lch == ch && ch == '_') {
  245.                 tk.yytext[tk.yyleng] = '\0';
  246.                 AVL_ERROR(strcat("Two _ repeated within numeric literal ==> ", tk.yytext));
  247.                 }
  248.             if (ch != '_')
  249.                 tk.yytext[tk.yyleng++] = ch;
  250.             lch = ch;
  251.             ch = AVL_NEXT();
  252.             } while (isdigit(ch) || ch == '_');
  253.         if (lch == '_') {
  254.             tk.yytext[tk.yyleng] = '\0';
  255.             AVL_ERROR(strcat("_ can't terminate an integer ==> ", tk.yytext));
  256.             }
  257.         if (ch == ':' || ch == '#')  { /* Got a based number */
  258.             is_based = ch;
  259.             tk.yytext[tk.yyleng] = '\0';
  260.             base = atoi(tk.yytext);
  261.             if (base < 2 || base > 16) 
  262.                 AVL_ERROR(strcat("Based literal with invalid base ==> ", tk.yytext));
  263.             tk.yyleng = 0;
  264.             ch = AVL_NEXT();
  265.             if (!IS_DIGIT(ch,base,&temp))
  266.                 AVL_ERROR("A digit was expected");
  267.             lch = ' ';
  268.             do {
  269.                 if (lch == ch && ch == '_') {
  270.                     tk.yytext[tk.yyleng] = '\0';
  271.                     AVL_ERROR(strcat("Two _ repeated within numeric literal ==> ", tk.yytext));
  272.                     }
  273.                 if (ch != '_')
  274.                     tk.yytext[tk.yyleng++] = ch;
  275.                 lch = ch;
  276.                 ch = AVL_NEXT();
  277.                 }  while (IS_DIGIT(ch,base,&temp) || ch == '_');
  278.             if (lch == '_') {
  279.                 tk.yytext[tk.yyleng] = '\0';
  280.                 AVL_ERROR(strcat("_ can't terminate an integer ==> ", tk.yytext));
  281.                 }
  282.             }
  283.         if (ch == io_size.decimal_point) { /* Got a real number? */
  284.             if (ch == '.')  {
  285.                 ch = AVL_NEXT();
  286.                 if (ch == '.')  {
  287.                     BACK('.');
  288.                     BACK('.');
  289.                     tk.yytext[tk.yyleng] = '\0';
  290.                     tk.code = XINTEGERLIT;
  291.                     return tk;
  292.                     }
  293.                 BACK(ch);
  294.                 }
  295.             is_real = 1;
  296.             tk.yytext[tk.yyleng++] = '.';
  297.             ch = AVL_NEXT();
  298.             if (!IS_DIGIT(ch,base,&temp))  {
  299.                 tk.yytext[tk.yyleng] = '\0';
  300.                 AVL_ERROR(strcat("A digit should follow a decimal point ==> ", tk.yytext));
  301.                 }
  302.             lch = ' ';
  303.             do {
  304.                 if (lch == ch && ch == '_') {
  305.